<div class="content-section introduction">
    <div class="feature-intro">
        <h1>FilterService</h1>
        <p>FilterService is a helper utility to filter collections against constraints. Example below demonstrates how to use a custom rule within Table.</p>
    </div>
    <app-demoActions github="filterservice" stackblitz="filterservice-demo"></app-demoActions>
</div>

<div class="content-section implementation p-fluid">
    <div class="card">
        <p-table #dt [columns]="cols" [value]="cars" [paginator]="true" [rows]="10" responsiveLayout="scroll">
            <ng-template pTemplate="header" let-columns>
                <tr>
                    <th *ngFor="let col of columns">
                        &#123;&#123;col.header&#125;&#125;
                    </th>
                </tr>
                <tr>
                    <th *ngFor="let col of columns">
                        <p-columnFilter type="text" [field]="col.field" [matchModeOptions]="matchModeOptions" [matchMode]="'custom-equals'"></p-columnFilter>
                    </th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-rowData let-columns="columns">
                <tr [pSelectableRow]="rowData">
                    <td *ngFor="let col of columns">
                        &#123;&#123;rowData[col.field]&#125;&#125;
                    </td>
                </tr>
            </ng-template>
        </p-table>
    </div>
</div>

<div class="content-section documentation">
    <p-tabView>
        <p-tabPanel header="Documentation">
            <h5>Import</h5>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
import &#123;FilterService&#125; from 'primeng/api';
</app-code>

            <h5>Getting Started</h5>
            <p>FilterService needs to be injected into your component.</p>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
export class FilterServiceDemo implements OnInit &#123;

    constructor(private filterService: FilterService) &#123;&#125;

    ngOnInit() &#123;
        const value = 'PrimeNG';

        this.filterService.filters.equals(value, 'NG');                            //false
        this.filterService.filters.equals(value, 8);                               //false
        this.filterService.filters.equals(value, new Date());                      //false
        this.filterService.filters.contains(value, 'NG');                          //true
        this.filterService.filters.startsWith(value, 'NG');                        //false
        this.filterService.filters.endsWith(value, 'NG');                          //true
        this.filterService.filters.lt(10, 20);                                     //true
        this.filterService.filters.gt(50, 20);                                     //true
        this.filterService.filters.in(value, ['PrimeFaces', 'PrimeNG']);           //true
    &#125;
&#125;
</app-code>

            <h5>Custom Constraint</h5>
            <p>FilterService can be extended by adding new constraints using the <span>register</span> function.</p>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
this.filterService.register('isPrimeNumber', (value, filter): boolean => &#123;
    if (filter === undefined || filter === null || filter.trim() === '') &#123;
        return true;
    &#125;

    if (value === undefined || value === null) &#123;
        return false;
    &#125;

    return value.toString() === filter.toString();
&#125;);

this.filterService.filters['isPrimeNumber'](3);                      //true
this.filterService.filters['isPrimeNumber'](5);                      //true
this.filterService.filters['isPrimeNumber'](568985673);              //false
</app-code>

            <h5>Built-in Constraints</h5>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Parameters</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>startsWith</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value starts with the filter value</td>
                        </tr>
                        <tr>
                            <td>contains</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value contains the filter value</td>
                        </tr>
                        <tr>
                            <td>endsWith</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value ends with the filter value</td>
                        </tr>
                        <tr>
                            <td>equals</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value equals the filter value</td>
                        </tr>
                        <tr>
                            <td>notEquals</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value does not equal the filter value</td>
                        </tr>
                        <tr>
                            <td>in</td>
                            <td>value: Value to filter<br />
                                filter[]: An array of filter values<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value contains the filter value</td>
                        </tr>
                        <tr>
                            <td>lt</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value is less than the filter value</td>
                        </tr>
                        <tr>
                            <td>lte</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value is less than or equals to the filter value</td>
                        </tr>
                        <tr>
                            <td>gt</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value is greater than the filter value</td>
                        </tr>
                        <tr>
                            <td>gte</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value is greater than or equals to the filter value</td>
                        </tr>
                        <tr>
                            <td>is</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value equals the filter value, alias to equals</td>
                        </tr>
                        <tr>
                            <td>isNot</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the value does not equal the filter value, alias to notEquals.</td>
                        </tr>
                        <tr>
                            <td>before</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the date value is before the filter date.</td>
                        </tr>
                        <tr>
                            <td>after</td>
                            <td>value: Value to filter<br />
                                filter: Filter value<br />
                                filterLocale: Locale to use in filtering</td>
                            <td>Whether the date value is after the filter date.</td>
                        </tr>
                    </tbody>
                </table>

                <h5>FilterService API</h5>
                <div class="doc-tablewrapper">
                    <table class="doc-table">
                        <thead>
                            <tr>
                                <th>Name</th>
                                <th>Parameters</th>
                                <th>Description</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>filter</td>
                                <td>value[]: An array of values to filter<br />
                                    fields[]: An array of properties in the value object<br />
                                    filterValue: Filter value<br />
                                    filterMatchMode: Constraint<br />
                                    filterLocale: Locale to use in filtering</td>
                                <td>Whether the property values of the given value collection matches the filter.</td>
                            </tr>
                            <tr>
                                <td>filters</td>
                                <td>-</td>
                                <td>Property to access constraints collection.</td>
                            </tr>
                            <tr>
                                <td>register</td>
                                <td>name: string <br />
                                    fn: Filter callback</td>
                                <td>Registers a new constraint in filters.</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>

            <h5>Dependencies</h5>
            <p>None.</p>
        </p-tabPanel>

        <p-tabPanel header="Source">
            <a href="https://github.com/primefaces/primeng/tree/master/src/app/showcase/components/filterservice" class="btn-viewsource" target="_blank">
                <span>View on GitHub</span>
            </a>
            <a href="https://stackblitz.com/edit/primeng-filterservice-demo" class="btn-viewsource" style="margin-left: .5em;" target="_blank">
                <span>Edit in StackBlitz</span>
            </a>
<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;p-table #dt [columns]="cols" [value]="cars" [paginator]="true" [rows]="10"&gt;
    &lt;ng-template pTemplate="header" let-columns&gt;
        &lt;tr&gt;
            &lt;th *ngFor="let col of columns"&gt;
                &#123;&#123;col.header&#125;&#125;
            &lt;/th&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th *ngFor="let col of columns"&gt;
                &lt;p-columnFilter type="text" [field]="col.field" [matchModeOptions]="matchModeOptions" [matchMode]="'custom-equals'"&gt;&lt;/p-columnFilter&gt;
            &lt;/th&gt;
        &lt;/tr&gt;
    &lt;/ng-template&gt;
    &lt;ng-template pTemplate="body" let-rowData let-columns="columns"&gt;
        &lt;tr [pSelectableRow]="rowData"&gt;
            &lt;td *ngFor="let col of columns"&gt;
                &#123;&#123;rowData[col.field]&#125;&#125;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/ng-template&gt;
&lt;/p-table&gt;
</app-code>

<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
import &#123; Component, OnInit &#125; from '@angular/core';
import &#123; CarService &#125; from '../../service/carservice';
import &#123; Car &#125; from '../../domain/car';
import &#123; SelectItem, FilterService, FilterMatchMode &#125; from 'primeng/api';

@Component(&#123;
    templateUrl: './filterservicedemo.html'
&#125;)
export class FilterServiceDemo implements OnInit &#123;

    cars: Car[];

    cols: any[];

    matchModeOptions: SelectItem[];

    constructor(private carService:CarService, private filterService: FilterService) &#123;&#125;

    ngOnInit() &#123;
        const customFilterName = 'custom-equals';

        this.filterService.register(customFilterName, (value, filter): boolean => &#123;
            if (filter === undefined || filter === null || filter.trim() === '') &#123;
                return true;
            &#125;

            if (value === undefined || value === null) &#123;
                return false;
            &#125;

            return value.toString() === filter.toString();
        &#125;);

        this.cols = [
            &#123; field: 'year', header: 'Year' &#125;,
            &#123; field: 'brand', header: 'Brand' &#125;,
            &#123; field: 'color', header: 'Color' &#125;,
            &#123; field: 'vin', header: 'Vin' &#125;
        ];

        this.matchModeOptions = [
            &#123; label: 'Custom Equals', value: customFilterName &#125;,
            &#123; label: 'Starts With', value: FilterMatchMode.STARTS_WITH &#125;,
            &#123; label: 'Contains', value: FilterMatchMode.CONTAINS &#125;,
        ];

        this.carService.getCarsMedium().then(cars => this.cars = cars);
    &#125;
&#125;
</app-code>
        </p-tabPanel>
        <p-tabPanel header="StackBlitz">
            <ng-template pTemplate="content">
                <iframe src="https://stackblitz.com/edit/primeng-filterservice-demo?embed=1" style="width: 100%; height: 768px; border: none;"></iframe>
            </ng-template>
        </p-tabPanel>
    </p-tabView>
</div>
